#ifndef TYPECHECKER_H
#define TYPECHECKER_H

#include "UtilVisitors.h"

class TypeCheck : public RecursiveVisitor
{
public:
	TypeCheck() : failure(false) {}
	virtual void caseDefault(void *param);
	virtual void caseVarDeclInitializer(ASTVarDeclInitializer &host, void *param);
	virtual void caseVarDecl(ASTVarDecl &host, void *param);
	virtual void caseExprAnd(ASTExprAnd &host, void *param);
	virtual void caseExprOr(ASTExprOr &host, void *param);
	virtual void caseExprGT(ASTExprGT &host, void *param);
	virtual void caseExprGE(ASTExprGE &host, void *param);
	virtual void caseExprLT(ASTExprLT &host, void *param);
	virtual void caseExprLE(ASTExprLE &host, void *param);
	virtual void caseExprEQ(ASTExprEQ &host, void *param);
	virtual void caseExprNE(ASTExprNE &host, void *param);
	virtual void caseExprPlus(ASTExprPlus &host, void *param);
	virtual void caseExprMinus(ASTExprMinus &host, void *param);
	virtual void caseExprTimes(ASTExprTimes &host, void *param);
	virtual void caseExprDivide(ASTExprDivide &host, void *param);
	virtual void caseExprNot(ASTExprNot &host, void *param);
	virtual void caseExprNegate(ASTExprNegate &host, void *param);
	virtual void caseNumConstant(ASTNumConstant &host, void *param);
	virtual void caseFuncCall(ASTFuncCall &host, void *param);
	virtual void caseBoolConstant(ASTBoolConstant &host, void *param);
	virtual void caseStmtAssign(ASTStmtAssign &host, void *param);
	virtual void caseExprDot(ASTExprDot &host, void *param);
	virtual void caseExprArrow(ASTExprArrow &host, void *param);
	virtual void caseStmtFor(ASTStmtFor &host, void *param);
	virtual void caseStmtIf(ASTStmtIf &host, void *param);
	virtual void caseStmtIfElse(ASTStmtIfElse &host, void *param);
	virtual void caseStmtReturn(ASTStmtReturn &host, void *param);
	virtual void caseStmtReturnVal(ASTStmtReturnVal &host, void *param);
	virtual void caseStmtWhile(ASTStmtWhile &host, void *param);
	virtual void caseExprBitOr(ASTExprBitOr &host, void *param);
	virtual void caseExprBitXor(ASTExprBitXor &host, void *param);
	virtual void caseExprBitAnd(ASTExprBitAnd &host, void *param);
	virtual void caseExprLShift(ASTExprLShift &host, void *param);
	virtual void caseExprRShift(ASTExprRShift &host, void *param);
	virtual void caseExprModulo(ASTExprModulo &host, void *param);
	virtual void caseExprBitNot(ASTExprBitNot &host, void *param);
	virtual void caseExprIncrement(ASTExprIncrement &host, void *param);
	virtual void caseExprDecrement(ASTExprDecrement &host, void *param);
	bool isOK() {return !failure;}
	void fail() {failure = true;}
	friend class GetLValType;
private:
	bool failure;
	bool standardCheck(int firsttype, int secondtype, AST *toblame);
};

class GetLValType : public ASTVisitor
{
public:
	virtual void caseDefault(void *param);
	virtual void caseExprDot(ASTExprDot &host, void *param);
	virtual void caseVarDecl(ASTVarDecl &host, void *param);
	virtual void caseExprArrow(ASTExprArrow &host, void *param);
};

#endif
